package wiki.xsx.jg.core;

import java.math.BigDecimal;
import java.sql.Time;
import java.util.*;

/**
 * MySQL实现类
 */
public class MySQLService extends AbstractService {

    public MySQLService(Database database) {
        super(database);
    }

    @Override
    public String getDropTableSQL(String className) {
        StringBuilder sql = new StringBuilder();
        sql.append("DROP TABLE IF EXISTS `").append(super.getDatabase().getName()).append("`.").append(className);
        return sql.toString();
    }

    @Override
    public Map<String, Object> getCreateTableSQLMap(Entity entity) {
        Map<String, Object> SQLMap = new HashMap<>();
        Queue<String> commentQueue = new LinkedList<>();
        StringBuilder pk = new StringBuilder();
        StringBuilder sql = new StringBuilder();
        sql.append("CREATE TABLE ").append(entity.getName()).append("(");
        for (Field field : entity.getColumnSet()){
            sql.append("`").append(field.getName()).append("` ");
            if (field.getType()!=null){
                sql.append(field.getType());
            }else{
                sql.append(getDataType(field.getJavaType()));
            }
            if (field.getIsNotNull()){
                sql.append(" NOT NULL ");
            }
            if (field.getDefaultValue()!=null){
                sql.append(" DEFAULT ").append(field.getDefaultValue());
            }
            if (field.getIsAutoIncrement()){
                sql.append(" AUTO_INCREMENT ");
            }
            if (field.getComment()!=null){
                sql.append(" COMMENT '").append(field.getComment()).append("'");
            }
            sql.append(",");
            if (field.getIsPrimaryKey()){
                pk.append("`").append(field.getName()).append("`,");
            }
        }
        if (pk.length()>0){
            sql.append("PRIMARY KEY (").append(pk.substring(0, pk.length()-1)).append(")");
        }else{
            sql = sql.deleteCharAt(sql.length()-1);
        }
        sql.append(") ");
        if (entity.getComment()!=null){
            sql.append("COMMENT='").append(entity.getComment()).append("'");
        }
        SQLMap.put("createSQL", sql.toString());
        SQLMap.put("commentSQL", commentQueue);
        return SQLMap;
    }

    @Override
    public Class<?> getTypeClass(String dataTypeName, int length, int scale) {
        if (dataTypeName.matches("CHAR|VARCHAR")){
            return String.class;
        }else if(dataTypeName.matches("TINYINT|SMALLINT|MEDIUMINT|INT|INTEGER|YEAR")) {
            return Integer.class;
        }else if(dataTypeName.matches("BIGINT")) {
            return Long.class;
        }else if(dataTypeName.matches("FLOAT")) {
            return Float.class;
        }else if(dataTypeName.matches("DOUBLE")) {
            return Double.class;
        }else if(dataTypeName.matches("DECIMAL")) {
            return BigDecimal.class;
        }else if(dataTypeName.matches("DATE|DATETIME|TIMESTAMP")) {
            return Date.class;
        }else if(dataTypeName.matches("TIME")) {
            return Time.class;
        }else if(dataTypeName.matches("BINARY|VARBINARY|TINYBLOB|BLOB|MEDIUMBLOB|LONGBLOB")) {
            return byte[].class;
        }else{
            return Object.class;
        }
    }

    @Override
    public String getDataType(Class<?> type) {
        StringBuilder builder = new StringBuilder();
        switch (type.getSimpleName().toLowerCase()){
            case "string":
                builder.append("VARCHAR(255)");
                break;
            case "integer":
                builder.append("INT");
                break;
            case "long":
                builder.append("BIGINT");
                break;
            case "float":
                builder.append("FLOAT");
                break;
            case "double":
                builder.append("DOUBLE");
                break;
            case "bigdecimal":
                builder.append("DECIMAL");
                break;
            case "date":
                builder.append("TIMESTAMP");
                break;
            case "time":
                builder.append("TIME");
                break;
            case "byte[]":
                builder.append("BLOB");
                break;
            default:
                builder.append("VARCHAR(255)");
        }
        return builder.toString();
    }
}
